
#include "vector2.h"

void vector2_create(float x, float y, struct vector2* v_out)
{
	v_out->x = x;
	v_out->y = y;
}
void vector2_add(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	v_out->x = v1->x + v2->x;
	v_out->y = v1->y + v2->y;
}
void vector2_barycentric(const struct vector2* v1, const struct vector2* v2, 
					  const struct vector2* v3, float amt1, float amt2, 
					  struct vector2* v_out)
{
	float amt1_1 = amt1;
	float amt2_2 = amt2;
	v_out->x = v1->x + amt1_1 * (v2->x - v1->x) + amt2_2 * (v3->x - v1->x);
	v_out->y = v1->y + amt1_1 * (v2->y - v1->y) + amt2_2 * (v3->y - v1->y);
}
void vector2_catmullrom(const struct vector2* v1, const struct vector2* v2,
					 const struct vector2* v3, const struct vector2* v4,
					 float amt, struct vector2* v_out)
{
	float single = amt * amt;
	float single1 = amt * single;
	float amt1 = amt;
	v_out->x = 0.5f * (2.0f * v2->x + (-v1->x + v3->x) * amt1 + (2.0f * v1->x - 5.0f * v2->x + 4.0f * v3->x - v4->x) * single + (-v1->x + 3.0f * v2->x - 3.0f * v3->x + v4->x) * single1);
	v_out->y = 0.5f * (2.0f * v2->y + (-v1->y + v3->y) * amt1 + (2.0f * v1->y - 5.0f * v2->y + 4.0f * v3->y - v4->y) * single + (-v1->y + 3.0f * v2->y - 3.0f * v3->y + v4->y) * single1);
}
void vector2_clamp(const struct vector2* v1, const struct vector2* min, const struct vector2* max, struct vector2* v_out)
{
	float x;
	float single;
	float single1;
	float y;
	float y1;
	float x1 = v1->x;

	if (x1 > max->x)
	{
		x = max->x;
	}
	else
	{
		x = x1;
	}
	x1 = x;
	if (x1 < min->x)
	{
		single = min->x;
	}
	else
	{
		single = x1;
	}
	x1 = single;
	single1 = v1->y;

	if (single1 > max->y)
	{
		y = max->y;
	}
	else
	{
		y = single1;
	}
	single1 = y;
	if (single1 < min->y)
	{
		y1 = min->y;
	}
	else
	{
		y1 = single1;
	}
	single1 = y1;
	v_out->x = x1;
	v_out->y = single1;
}
void vector2_dist(const struct vector2* v1, const struct vector2* v2, float* f_out)
{
	float x = v1->x - v2->x;
	float y = v1->y - v2->y;
	float single = (x * x) + (y * y);
	*f_out = sqrtf(single);
}
void vector2_distsqr(const struct vector2* v1, const struct vector2* v2, float* f_out)
{
	float x = v1->x - v2->x;
	float y = v1->y - v2->y;
	*f_out = (x * x) + (y * y);
}
void vector2_div(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	v_out->x = v1->x / v2->x;
	v_out->y = v1->y / v2->y;
}
void vector2_divf(const struct vector2* v, float div, struct vector2* v_out)
{
	float single = 1.0f / div;
	v_out->x = v->x * single;
	v_out->y = v->y * single;
}
void vector2_dot(const struct vector2* v1, const struct vector2* v2, float* f_out)
{
	*f_out = (v1->x * v2->x) + (v1->y * v2->y);
}
void vector2_equals(const struct vector2* v1, const struct vector2* v2, int* result)
{
	*result = 0;
	if (v1->x == v2->x)
	{
		if (v1->y == v2->y)
		{
			*result = 1;
		}
	}
}
void vector2_hermite(const struct vector2* v1, const struct vector2* tang1,
				  const struct vector2* v2, const struct vector2* tang2,
				  float amt, struct vector2* v_out)
{
	float single, single1, single2, single3, single4, single5;
	float amt1 = amt;

	single = amt1 * amt1;
	single1 = amt1 * single;
	single2 = 2.0f * single1 - 3.0f * single + 1.0f;
	single3 = -2.0f * single1 + 3.0f * single;
	single4 = single1 - 2.0f * single + amt1;
	single5 = single1 - single;

	v_out->x = v1->x * single2 + v2->x * single3 + tang1->x * single4 + tang2->x * single5;
	v_out->y = v1->y * single2 + v2->y * single3 + tang1->y * single4 + tang2->y * single5;
}
void vector2_len(const struct vector2* v, float* f_out)
{
	*f_out = sqrtf((v->x * v->x) + (v->y * v->y));
}
void vector2_lensqr(const struct vector2* v, float* f_out)
{
	*f_out = (v->x * v->x) + (v->y * v->y);
}
void vector2_lerp(const struct vector2* v1, const struct vector2* v2,
			   float amt, struct vector2* v_out)
{
	float amt1 = amt;
	v_out->x = v1->x + (v2->x - v1->x) * amt1;
	v_out->y = v1->y + (v2->y - v1->y) * amt1;
}
void vector2_max(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	if (v1->x > v2->x)
	{
		v_out->x = v1->x;
	}
	else
	{
		v_out->x = v2->x;
	}
	if (v1->y > v2->y)
	{
		v_out->y = v1->y;
	}
	else
	{
		v_out->y = v2->y;
	}
}
void vector2_min(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	if (v1->x < v2->x)
	{
		v_out->x = v1->x;
	}
	else
	{
		v_out->x = v2->x;
	}
	if (v1->y < v2->y)
	{
		v_out->y = v1->y;
	}
	else
	{
		v_out->y = v2->y;
	}
}
void vector2_mult(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	v_out->x = v1->x * v2->x;
	v_out->y = v1->y * v2->y;
}
void vector2_multf(const struct vector2* v1, float scale, struct vector2* v_out)
{
	v_out->x = v1->x * scale;
	v_out->y = v1->y * scale;
}
void vector2_negate(const struct vector2* v, struct vector2* v_out)
{
	v_out->x = -v->x;
	v_out->y = -v->y;
}
void vector2_norm(const struct vector2* v, struct vector2* v_out)
{
	float x = v->x * v->x + v->y * v->y;
	float single = 1.0f / sqrtf(x);

	v_out->x = v->x * single;
	v_out->y = v->y * single;
}
void vector2_reflect(const struct vector2* vec, const struct vector2* normal, struct vector2* v_out)
{
	float x = vec->x * normal->x + vec->y * normal->y;

	v_out->x = vec->x - 2.0f * x * normal->x;
	v_out->y = vec->y - 2.0f * x * normal->y;
}
void vector2_smoothstep(const struct vector2* v1, const struct vector2* v2, float amt, struct vector2* v_out)
{
	float single, amt2;
	amt2 = amt;

	if (amt2 > 1.0f)
	{
		single = 1.0f;
	}
	else
	{
		if (amt2 < 0.0f)
		{
			single = 0.0f;
		}
		else
		{
			single = amt2;
		}
	}
	amt2 = single;
	amt2 = amt2 * amt2 * (3.0f - 2.0f * amt2);

	v_out->x = v1->x + (v2->x - v1->x) * amt2;
	v_out->y = v1->y + (v2->y - v1->y) * amt2;
}
void vector2_subt(const struct vector2* v1, const struct vector2* v2, struct vector2* v_out)
{
	v_out->x = v1->x - v2->x;
	v_out->y = v1->y - v2->y;
}
void vector2_transform_matrix4(const struct vector2* pos, const struct matrix4* matrix, struct vector2* v_out)
{
	float x = pos->x * matrix->m11 + pos->y * matrix->m21 + matrix->m41;
	float y = pos->x * matrix->m12 + pos->y * matrix->m22 + matrix->m42;
	v_out->x = x;
	v_out->y = y;
}
void vector2_transform_quaternion(const struct vector2* v, const struct quaternion* rotation, struct vector2* v_out)
{
	float x, y, z, w, x1, y1, z1, x2, single, single1;

	x = rotation->x + rotation->x;
	y = rotation->y + rotation->y;
	z = rotation->z + rotation->z;
	w = rotation->w * z;
	single = rotation->x * x;
	x1 = rotation->x * y;
	y1 = rotation->y * y;
	z1 = rotation->z * z;
	single1 = v->x * (1.0f - y1 - z1) + v->y * (x1 - w);
	x2 = v->x * (x1 + w) + v->y * (1.0f - single - z1);
	
	v_out->x = single1;
	v_out->y = x2;
}
void vector2_transformnormal(const struct vector2* normal, const struct matrix4* matrix, struct vector2* v_out)
{
	v_out->x = normal->x * matrix->m11 + normal->y * matrix->m21;
	v_out->y = normal->x * matrix->m12 + normal->y * matrix->m22;
}